Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
9:41
📶
📊
🔋
Todo List
Add
Reset
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -webkit-tap-highlight-color: transparent; } body { background-color: #f0f0f0; color: #fff; display: flex; justify-content: center; align-items: center; min-height: 100vh; transition: background-color 0.3s; } body.light-mode { background-color: #f0f0f0; } body.dark-mode { background-color: #121212; } .iphone { width: 375px; height: 812px; background-color: #1c1c1e; border-radius: 40px; overflow: hidden; position: relative; box-shadow: 0 0 0 10px #2c2c2e, 0 0 0 13px #000, 0 20px 50px rgba(0, 0, 0, 0.5); transition: background-color 0.3s, box-shadow 0.3s; } .light-mode .iphone { background-color: #ffffff; box-shadow: 0 0 0 10px #e0e0e0, 0 0 0 13px #bdbdbd, 0 20px 50px rgba(0, 0, 0, 0.2); } .notch { position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 200px; height: 30px; background-color: #000; border-bottom-left-radius: 20px; border-bottom-right-radius: 20px; z-index: 1000; } .status-bar { display: flex; justify-content: space-between; align-items: center; padding: 5px 20px; font-size: 14px; background-color: rgba(0, 0, 0, 0.3); transition: background-color 0.3s, color 0.3s; } .light-mode .status-bar { background-color: rgba(255, 255, 255, 0.3); color: #000; } .time { font-weight: bold; } .icons span { margin-left: 5px; } .app-container { height: calc(100% - 30px); overflow-y: auto; padding: 20px; color: #fff; transition: color 0.3s; } .light-mode .app-container { color: #000; } h1 { font-size: 32px; margin-bottom: 20px; font-weight: 700; } #task-form { display: flex; margin-bottom: 20px; } #task-input { flex-grow: 1; padding: 10px; border: none; background-color: #2c2c2e; color: #fff; border-radius: 10px 0 0 10px; font-size: 16px; transition: background-color 0.3s, color 0.3s; } .light-mode #task-input { background-color: #f0f0f0; color: #000; } button { border: none; background-color: #0a84ff; color: #fff; padding: 10px 15px; font-size: 16px; cursor: pointer; transition: background-color 0.3s; } #add-btn { border-radius: 0 10px 10px 0; } #reset-btn { border-radius: 10px; margin-left: 10px; background-color: #ff453a; } button:active { opacity: 0.8; } .task-list { list-style-type: none; } .task-item { background-color: #2c2c2e; border-radius: 10px; margin-bottom: 10px; overflow: hidden; transition: background-color 0.5s; } .completed { background-color: #22222255; color: #8888ff55; } .light-mode .completed { background-color: #0000ff55; color: #44449955; } .light-mode .task-item { background-color: #f0f0f0; } .task-header { display: flex; justify-content: space-between; align-items: center; padding: 15px; background-color: #3a3a3c; transition: background-color 0.3s; } .light-mode .task-header { background-color: #e0e0e0; } .task-title { font-weight: 600; font-size: 18px; } .task-actions { display: flex; gap: 10px; } .task-content { padding: 15px; } .task-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .completed .task-label { color: #8888ff55; } .light-mode .completed .task-label { color: #44449955; } .task-label { font-weight: 500; color: #8e8e93; transition: color 0.3s; } .light-mode .task-label { color: #6e6e73; } .progress-container { display: flex; align-items: center; width: 100%; margin-left: 10px; } progress { flex-grow: 1; height: 6px; border-radius: 3px; -webkit-appearance: none; } progress::-webkit-progress-bar { background-color: #48484a; border-radius: 3px; } .light-mode progress::-webkit-progress-bar { background-color: #d1d1d6; } progress::-webkit-progress-value { background-color: #30d158; border-radius: 3px; } .progress-value { margin-left: 10px; font-size: 14px; color: #8e8e93; transition: color 0.3s; } .light-mode .progress-value { color: #6e6e73; } input[type="date"] { background-color: #3a3a3c; border: none; color: #fff; padding: 5px; border-radius: 5px; transition: background-color 0.3s, color 0.3s; } .light-mode input[type="date"] { background-color: #e0e0e0; color: #000; } .completed .task-title { text-decoration: line-through; color: #8888ff55; } .light-mode .completed .task-title { background-color: #e0e0e0; color: #44449950; } .drag-handle { cursor: move; padding: 0 5px; color: #8e8e93; } .light-mode .drag-handle { color: #6e6e73; } #theme-toggle { position: absolute; top: 40px; right: 20px; background: none; border: none; font-size: 24px; cursor: pointer; z-index: 1001; } .delete-btn { background: none; border: none; cursor: pointer; padding: 5px; color: inherit; } .light-mode #theme-toggle { color: #000; } .due-date-row { display: flex; align-items: center; } .due-date-row input[type="checkbox"] { margin-right: 10px; } .due-date-row .task-label { margin-right: 10px; }
console.log("Event Fired") const taskForm = document.getElementById("task-form"); const taskInput = document.getElementById("task-input"); const taskList = document.getElementById("task-list"); const resetBtn = document.getElementById("reset-btn"); const themeToggle = document.getElementById("theme-toggle"); const defaultTasks = [ { id: 1, text: "Create a Pen", completed: false, progress: 0, dueDate: "2024-09-30" }, { id: 2, text: "Go for a walk", completed: false, progress: 10, dueDate: "2024-12-31" } ]; let tasks = [...defaultTasks]; let nextId = 3; function saveTasks() { localStorage.setItem("tasks", JSON.stringify(tasks)); } function renderTasks() { taskList.innerHTML = ""; tasks.forEach((task) => { const li = document.createElement("li"); li.className = `task-item${task.completed ? " completed" : ""}`; li.dataset.id = task.id; li.innerHTML = `
☰
${task.text}
Progress:
${task.progress}%
Due Date:
`; const checkbox = li.querySelector('.due-date-row input[type="checkbox"]'); checkbox.addEventListener("change", () => { task.completed = checkbox.checked; li.classList.toggle("completed", task.completed); saveTasks(); }); const dateInput = li.querySelector('input[type="date"]'); dateInput.addEventListener("change", () => { task.dueDate = dateInput.value; saveTasks(); }); const progressBar = li.querySelector("progress"); const progressValue = li.querySelector(".progress-value"); progressBar.addEventListener("click", (e) => { const rect = progressBar.getBoundingClientRect(); const clickPosition = e.clientX - rect.left; const progressPercentage = (clickPosition / rect.width) * 100; task.progress = Math.round(progressPercentage); progressBar.value = task.progress; progressValue.textContent = `${task.progress}%`; saveTasks(); }); const deleteBtn = li.querySelector(".delete-btn"); deleteBtn.addEventListener("click", () => { tasks = tasks.filter((t) => t.id !== task.id); renderTasks(); saveTasks(); }); taskList.appendChild(li); }); // Initialize drag and drop functionality new Sortable(taskList, { animation: 150, handle: ".drag-handle", onEnd: function (evt) { const itemEl = evt.item; const newIndex = evt.newIndex; const oldIndex = evt.oldIndex; // Update the tasks array const [movedTask] = tasks.splice(oldIndex, 1); tasks.splice(newIndex, 0, movedTask); saveTasks(); } }); } function resetTasks() { tasks = [...defaultTasks]; saveTasks(); renderTasks(); } taskForm.addEventListener("submit", (e) => { e.preventDefault(); const taskText = taskInput.value.trim(); if (taskText) { tasks.push({ id: nextId++, text: taskText, completed: false, progress: 0, dueDate: "" }); taskInput.value = ""; renderTasks(); saveTasks(); } }); resetBtn.addEventListener("click", resetTasks); // Load tasks from localStorage if available const savedTasks = localStorage.getItem("tasks"); if (savedTasks) { tasks = JSON.parse(savedTasks); nextId = Math.max(...tasks.map((t) => t.id)) + 1; } renderTasks(); // Update time in status bar function updateTime() { const now = new Date(); const timeString = now.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", hour12: true }); document.querySelector(".time").textContent = timeString; } updateTime(); setInterval(updateTime, 1000); // Theme toggle functionality themeToggle.addEventListener("click", () => { document.body.classList.toggle("light-mode"); document.body.classList.toggle("dark-mode"); themeToggle.innerHTML = document.body.classList.contains("light-mode") ? '
' : '
'; });